using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using CodePlex.Resourceful;

namespace CodePlex.SpaceBlock.UI.Controls.Explore
{
    public static class FilesControlModifiedContextMenu
    {

        private class TimeZoneInfo : IComparable<TimeZoneInfo>
        {
            public TimeSpan Offset;
            public string Name;

            public int CompareTo(TimeZoneInfo other)
            {
                return this.Offset.CompareTo(other.Offset);
            }
        }


        private static readonly int __lastModifiedColumnIndex = 3;
        private readonly static List<DataGridView> __allGrids = new List<DataGridView>();
        private readonly static object __timeZonesLock = new object();

        private static IEnumerable<TimeZoneInfo> __timeZones;
        private static TimeZoneInfo __selected;
 

        public static string FormatLastModified(DateTime? localValue)
        {
            if (!localValue.HasValue)
            {
                return null;
            }
            DateTime utcValue = localValue.Value.ToUniversalTime();

            string rt = utcValue.Add(__selected.Offset).ToString();

            return rt;

        }


        public static void Setup(ContextMenuStrip contextMenu, DataGridView grid)
        {
            __allGrids.Add(grid);

            contextMenu.ShowImageMargin = false;
            contextMenu.ShowCheckMargin = true;

            Operation<TimeZoneInfo> addMenuItem = delegate(TimeZoneInfo item) 
            {
                ToolStripMenuItem tsi = new ToolStripMenuItem();
                tsi.Text = item.Name;
                tsi.Tag = item;
                contextMenu.Items.Add(tsi);
            };

            addMenuItem(GetLocalTimeZone());
            addMenuItem(GetUTCTimeZone());
         
            contextMenu.Items.Add("-");

            Utils.ForEach(GetSystemTimeZones(), addMenuItem);
          
          



            ContextMenuStrip originalContextMenu = null;
            contextMenu.Closed += delegate
            {
                grid.ContextMenuStrip = originalContextMenu;
            };
            contextMenu.ItemClicked += delegate(object sender, ToolStripItemClickedEventArgs e)
            {
                TimeZoneInfo tzi = e.ClickedItem.Tag as TimeZoneInfo;
                if (tzi == null || __selected == tzi)
                {
                    return;
                }
                
                __selected = tzi;

                UpdateDates();
            };


            grid.MouseDown += delegate(object sender, MouseEventArgs e)
            {
                 foreach (ToolStripItem item in contextMenu.Items)
                 {
                     ToolStripMenuItem tsmi = item as ToolStripMenuItem;
                     if (tsmi == null)
                     {
                         continue;
                     }
                     TimeZoneInfo tzi = tsmi.Tag as TimeZoneInfo;

                     tsmi.Checked = __selected.Name.Equals(tzi.Name);
                 }


                 // right click on "modified" column -> show time zone selector
                 System.Windows.Forms.DataGridView.HitTestInfo info = grid.HitTest(e.X, e.Y);

                 if (e.Button == MouseButtons.Right 
                     && info.Type == DataGridViewHitTestType.ColumnHeader 
                     && info.ColumnIndex == __lastModifiedColumnIndex)
                 {
                     originalContextMenu = grid.ContextMenuStrip;
                     grid.ContextMenuStrip = contextMenu;
                 }
             };

            if (__selected == null)
            {
                __selected = GetLocalTimeZone();
            }

            UpdateDates();
        }




    






        private static void UpdateDates()
        {
            foreach (DataGridView grid in __allGrids)
            {
                foreach (DataGridViewRow row in grid.Rows)
                {
                    IFileItem file = row.Tag as IFileItem;
                    if (file != null)
                    {
                        row.Cells[__lastModifiedColumnIndex].Value = FormatLastModified(file.LastModified.Value);
                    }

                }
            }
        }

        private static IEnumerable<TimeZoneInfo> GetSystemTimeZones()
        {
            return Utils.Sort(AllTimeZones());
        }

        private static TimeZoneInfo GetLocalTimeZone()
        {

            //try
            //{
            //    string currentName = TimeZoneInformation.CurrentTimeZone.DisplayName;
            //    return Utils.Find(AllTimeZones(), delegate(TimeZoneInfo item)
            //    {
            //        return item.Name == currentName;
            //    });

            //}
            //catch
            //{
                TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
                return Utils.Find(AllTimeZones(), delegate(TimeZoneInfo item)
                {
                    return item.Offset.TotalHours == offset.Hours;
                });
           // }

        }
       
        private static IEnumerable<TimeZoneInfo> AllTimeZones()
        {
            lock (__timeZonesLock)
            {
                if (__timeZones == null)
                {
                    //try
                    //{
                    //    sTimeZones = Utils.ConvertAll<TimeZoneInformation, TimeZoneInfo>(TimeZoneInformation.EnumZones(), delegate(TimeZoneInformation item)
                    //    {
                    //        TimeZoneInfo rt = new TimeZoneInfo();
                    //        rt.Offset = TimeSpan.FromMinutes(item.Bias);
                    //        rt.Name = item.DisplayName;
                    //        return rt;
                    //    });
                    //}
                    //catch
                    //{
                        List<TimeZoneInfo> rt = new List<TimeZoneInfo>();
                        for (int i = -12; i <= 13; i++)
                        {
                            TimeZoneInfo rti = new TimeZoneInfo();
                            rti.Offset = TimeSpan.FromHours(i);
                            if (i == 0)
                            {
                                rti.Name = "(GMT)";
                            }
                            else
                            {
                                rti.Name = string.Format(
                                    "(GMT{0}{1}:00)",
                                    Math.Sign(i) > 0 ? "+" : "-",
                                    Math.Abs(i).ToString().PadLeft(2, '0')
                                );
                            }

                            rt.Add(rti);
                        }
                        __timeZones = rt;
                   // }
                }
                return __timeZones;
            }
        }
        private static TimeZoneInfo GetUTCTimeZone()
        {
            return Utils.Find(AllTimeZones(), delegate(TimeZoneInfo item)
            {
                return item.Offset.TotalHours == 0;
            });
        }


    }
}
